#ifndef _CLIENT_
#define _CLIENT_
#include "ExampleClient.h"
#include "threadPool.hpp"

template<typename MessageType>
bool ExampleClient<MessageType>::ReadReady()
{
    //read the size of data(4 bytes).
    while(!sizeIsRead)
    {
        int bytesAvil=recv(fd_,&packetSize,sizeof(int),MSG_PEEK);
        if(bytesAvil<sizeof(int))
        {
            continue;
        }
        recv(fd_,&packetSize,sizeof(int),0);
        packetSize=ntohl(packetSize);
        sizeIsRead=true;
        break;
    }
    while(bytes_read<packetSize)
    {
        memset(buffer,0,1024);
        int ret=recv(fd_,buffer,packetSize-bytes_read,0);
        if(ret<0)
        {
            if((errno==EAGAIN)||(errno==EWOULDBLOCK))
            {
                cout<<"read later."<<endl;
                return true;;
            }
            cout<<"can not read data."<<endl;
            return false;
        }
        else if(ret==0)
        {
            //cout<<"client close the connection."<<endl;
            return false;
        }
        else
        {
            bytes_read+=ret;
            data_buffer.append(buffer,ret);
        }
    }
    MessageType *tmp=new MessageType(data_buffer,fd_);
    threadpool<MessageType>::getInstance()->append(tmp);
    data_buffer.clear();
    sizeIsRead=false;
    packetSize=0;
    bytes_read=0;
    return true;
}

template<typename MessageType>
bool ExampleClient<MessageType>::WriteReady()
{
	//I give a possible implemention of code when EPOLLOUT event is triggered.
    /*
		auto data=data_map.find(_fd);
		char *buf=data.buf;
		if(strlen(buf)==0) return;
		int dataSize=data.dataSize;
		int dataHaveWrite=data.dataHaveWrite;
		n = dataSize;  
		while (n > 0) {  
			nwrite = write(fd, buf + dataHaveWrite + dataSize - n, n);  
			if (nwrite < n) {
				if (nwrite == -1 && errno != EAGAIN) {  
					perror("write error");  
				}  
			break;  
			}  
		n -= nwrite;  
		}
		if(data_size==0){
			//clear the data of this item.
		}
		
    */
    return true;
}

template<typename MessageType>
bool ExampleClient<MessageType>::HeartBeat()
{
    //if no operations occurred during timeout period return false to signal server to close socket
    if(static_cast<time_t>(last_active_ + timeout_) < time(0))
    {
        printf("[i] connection %s:%d has timed out\n", inet_ntoa(client_addr_), client_port_);
        return false;
    }

    return true;
}

template<typename MessageType>
void ExampleClient<MessageType>::ClientClose()
{
    close(fd_);

    printf("[-] connection %s:%d closed by client\n", inet_ntoa(client_addr_), client_port_);
}

template<typename MessageType>
void ExampleClient<MessageType>::ServerClose()
{
    close(fd_);
    printf("[-] connection %s:%d closed by server\n", inet_ntoa(client_addr_), client_port_);
}

#endif
